package com.net.entity;

import com.net.Client;
import com.tank.control.DirectionEnum;
import com.tank.entrity.GroupType;
import com.tank.entrity.Tank;
import com.tank.model.GameModel;
import lombok.Cleanup;
import lombok.SneakyThrows;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.util.UUID;

@Slf4j
@ToString
public class TankJoinMessage extends Message {
    public double x, y;
    public DirectionEnum dir;
    public boolean moving;
    public GroupType group;
    public UUID id;



    public TankJoinMessage(Tank tank) {
        this.x = tank.getX();
        this.y = tank.getY();
        this.dir = tank.getDirectionEnum();
        this.group = tank.getGroupType();
        this.id = tank.getUuid();
        this.moving = tank.isMoving();
    }

    public TankJoinMessage(int x, int y, DirectionEnum dir, boolean moving, GroupType group, UUID id) {
        super();
        this.x = x;
        this.y = y;
        this.dir = dir;
        this.moving = moving;
        this.group = group;
        this.id = id;
    }

    public TankJoinMessage() {
    }

    @SneakyThrows
    public void parse(byte[] bytes) {
        @Cleanup DataInputStream dis = new DataInputStream(new ByteArrayInputStream(bytes));
        this.x = dis.readInt();
        this.y = dis.readInt();
        this.dir = DirectionEnum.values()[dis.readInt()];
        this.moving = dis.readBoolean();
        this.group = GroupType.values()[dis.readInt()];
        this.id = new UUID(dis.readLong(), dis.readLong());
    }

    /**
     * 整个消息转化为一个byte数组
     * @return byte
     */
    @SneakyThrows
    @Override
    public byte[] toBytes() {
        @Cleanup ByteArrayOutputStream baos = new ByteArrayOutputStream();
        @Cleanup DataOutputStream dos = new DataOutputStream(baos);
        byte[] bytes = null;

        dos.writeInt((int) x);
        dos.writeInt((int) y);
        dos.writeInt(dir.ordinal());
        dos.writeBoolean(moving);
        dos.writeInt(group.ordinal());
        // 高64位
        dos.writeLong(id.getMostSignificantBits());
        // 低64位
        dos.writeLong(id.getLeastSignificantBits());
        dos.flush();
        bytes = baos.toByteArray();
        return bytes;
    }

    @Override
    public void handle() {
        if(this.id.equals(((Tank)GameModel.INSTANCE.getMainTank()).getUuid()) ||
                GameModel.INSTANCE.findTankByUUID(this.id) != null) {
            return;
        }
        Tank t = new Tank(this);
        GameModel.INSTANCE.addTank(t);
        log.info("client send start....");
        // send a new TankJoinMsg to the new joined tank
        Client.INSTANCE.send(new TankJoinMessage((Tank) GameModel.INSTANCE.getMainTank()));
    }

    @Override
    public MessageType getMessageType() {
        return MessageType.TankJoin;
    }
}
